﻿//----------------------------------------------------------------
// Desc: 
// Edit: ShowLong, http://blog.csdn.net/showlong
//
// Date Created: 2012-09-11
//
// Update Date : 
//
// Copyright (c) Fuel4D (http://www.fuel4d.com), All rights reserved.
//
//----------------------------------------------------------------
#pragma once


//-----------------------------------------------------------------
// 公共性能服务
//-----------------------------------------------------------------
// 获取性能服务
class IFProfileService;
extern FAPI IFProfileService* FPF_GetService();
// 函数进入和跳出时调用以下两个配对函数进行性能统计
extern FAPI void FPF_FuncEnter(const ACHAR* name);
extern FAPI void FPF_FuncLeave(const ACHAR* name);
// 自动函数调用消耗统计
#define FPF_FuncAuto FPF_AutoFunc_ __auto_func__(_FFUNCA_)
// 自动函数调用消耗统计，但名字自定义
#define FPF_FuncName(x) FPF_AutoFunc_ __auto_func__(x)
// 注册一个函数
extern FAPI void FPF_FuncRegister(const ACHAR* name);
// 获取某个性能对象数据
class IFProfileObject;
typedef FVector< IFProfileObject* > FV_PROFILE_OBJECT;
extern FAPI IFProfileObject* FPF_GetProfile(const ACHAR* name, EF_PF_TYPE mk);
// 获取某个类型的多个信息
extern FAPI void FPF_GetProfileList(EF_PF_TYPE mk, FV_PROFILE_OBJECT& vout, size_t max_out);
// 设置性能输入日志位置
// .p 空或者0表示恢复默认位置
extern FAPI void FPF_SetProfileOutFilepath(const ACHAR* p);


//-----------------------------------------------------------------
// 性能对象及对象的数据获取方法
//-----------------------------------------------------------------
class IFProfileObject : public IFMemObject
{
    FDECLARE_STRUCT(IFProfileObject)

public:
    enum EPF_PROP_TYPE
    {
        // 函数调用
        eFUNC_CALL_COUNT,   // 函数总调用次数           : UINT64*
        eFUNC_CALL_TIME,    // 函数总调用时间           : double*
        eFUNC_CALL_MIN,     // 函数最小开消时间         : double*
        eFUNC_CALL_MAX,     // 函数最大开消时间         : double*
        eFUNC_CALL_NOW,     // 当前帧调用时间开消       : double*

        // FPS统计
        eFPS_MIN,           // 最小FPS                  : float*
        eFPS_AVERAGE,       // 平均FPS                  : double*
    };

    IFProfileObject(const ACHAR* n, BYTE t, FDATA_ID h)
        :nType(t)
        ,nHash(h)
        ,szName(n)
    {}

    // 打出输出结果
    virtual void OutResult(FStringA& result) = 0;
    // 获取特定参数（不同的性能计数器支持的类型不同）
    virtual bool GetProperty(EPF_PROP_TYPE type, DWORD_PTR prop){ return false; }

    const BYTE nType;           // 类型
    const FDATA_ID nHash;       // HASH值
    const ACHAR* szName;        // 名字

protected:
    IFProfileObject& operator = (const IFProfileObject& r){ return *this; }
};


//-----------------------------------------------------------------
// 性能服务器（程序启动开启自动统计）
//-----------------------------------------------------------------
class IFProfileService : public IFMemObject
{
public:
    virtual~IFProfileService()
    {}

    // 程序每帧最先调用，或者不调用
    virtual void Idle(float last_fps) = 0;
    // 停止统计，仅停止，不清理数据（需要Idle单帧处理支持，且在下一帧到来时才会真正停止）
    virtual void Stop() = 0;
    // 启动统计，恢复统计（需要Idle单帧处理支持，且在下一帧到来时才会真正开始）
    virtual void Start() = 0;
    // 清空统计数据（下一帧到来时才会真正时候清理）
    virtual void Clear() = 0;
    // 获取指定性能对象
    virtual IFProfileObject* Get(const ACHAR* name, EF_PF_TYPE mk) = 0;
    // 获取当前时间（从性能计数器启动到现在的时间）
    virtual double GetTime() = 0;
    // 输出当前性能统计结果到文件
    // ePFT_COUNT 表示打印所有
    virtual void OutFile(const ACHAR* filename, EF_PF_TYPE mk = ePFT_COUNT) = 0;
    // 立即根据相关设置输出当前的性能信息到日志文件
    virtual void ImmediateOutLog() = 0;
};


//-----------------------------------------------------------------
// 函数性能自动处理机
//-----------------------------------------------------------------
class FPF_AutoFunc_
{
public:
    FPF_AutoFunc_(const ACHAR* name)
        :func_name(name)
    {
        FPF_FuncEnter(name);
    }
    ~FPF_AutoFunc_()
    {
        FPF_FuncLeave(func_name);
    }
    const ACHAR* func_name;
};